
# 1.函数和方法的初认识
# def eat():
#     print('调用eat()函数')
#
# eat()
#
# class Person:
#     # 实例方法
#     def eat2(self):
#         print('调用eat2方法')
#
# p = Person()
# p.eat2()

# 2.方法的划分
# 方法划分依据：方法第一个参数的数据类型
# A、类方法 （第一个参数是类）B、实例方法（第一个参数是实例）  C、静态方法（没有参数）
# class Person:
#     # 这是一个实例方法，第一个参数必须接收一个实例 ,只有实例调用
#     def test(self):
#         print('这是一个实例方法，第一个参数必须接收一个实例', self)
#
#     # 这是一个类方法，第一个参数必须接收一个类 实例和类都可以调用
#     @classmethod
#     def leifangfa(cls):
#         print('这是一个类方法，第一个参数必须接收一个类', cls)
#
#     # 这是一个静态方法，没有参数  实例和类都可以调用
#     @staticmethod
#     def jintafanfa():
#         print('这是一个静态方法，没有参数')


# p = Person()
# p.test()
# p.leifangfa()
# p.jintafanfa()
# Person.leifangfa()
# Person.jintafanfa()
# print(Person.__dict__)


# 3.类里面各种方法 都是存放在类的字典里面 不是__dict__字典属性字典

# 4. 实例方法: 就是直接调用函数本身的实现逻辑
# class Person:
#     def eat(self, food):
#         print('在吃。。。。', self, food)
#
#
# # 常规调用
# p = Person()
# p.eat('土豆')
# Person.eat('1232', '类方法调用')
#
# # 不常规调用
# func = Person.eat
# func('sdafsa', 'dsafads')

# 5. 类方法
# class Person:
#     @classmethod
#     def eat(cls, food):
#         print('类方法再吃。。', cls, food)
#
# class zhangsan(Person):
#     pass
#
# # 正常调用
# Person.eat('水谷')
# p = Person()
# p.eat('sdadsa')
#
# zhangsan.eat('子类的事物')
#
# # 不常规调用
# func = Person.eat
# func('dsfasfdafasdfsafsad')

# 6.静态方法
# class Person:
#     @staticmethod
#     def eat(food):
#         print('这是一个静态方法', food)
#
#
# Person.eat('ddd')
# p = Person()
# p.eat('ttttt')

# # 7.不同方法里面访问不同属性的权限问题  方法里面能拿到实例就只能访问实例属性  方法里面能拿到类，就能拿到类属性
# class Person:
#     age = 10
#     name = '刘子彬'
#
#     def eatinstantce(self):
#         print('这是一个实例方法', self)
#         print(self)
#         print(self.number)
#
#     @classmethod
#     def eatClass(cls):
#         print('这是一个类方法', cls)
#         print(cls.age)
#         print(cls.name)
#
#     @staticmethod
#     def eatstatic():
#         print('这是一个静态方法')
#
# p = Person()
# p.number = 15

# # 访问类属性
# print(p.age)
# print(Person.age)
#
# # 方法实例属性
# print(p.number)

# Person.eatClass()
# Person.eatstatic()

# p.eatstatic()
# p.eatinstantce()
# p.eatClass()



# 8 、私有化方法 与 私有化属性一样 都是加__
class Person(object):
    # 私有属性
    __age = 10

    # 私有方法 _Person__run()
    def __run(self):
        print('xxxxxxx')

    # 覆盖了__run方法  不能这么定义
    def _Person__run(self):
        print('ddd')

# 9、类内置的特殊方法

# --------------------------------9.1 信息格式化操作----------------------
# class Person(object):
#     def __init__(self, name, age):
#         self.age = age
#         self.name = name
#
#     # 打印对象的内容 - 描述对象
#     def __str__(self):
#         return '这个人的姓名是：%s, 这是人的年龄是：%s'%(self.name, self.age)
#
#
# p1 = Person('zb', 30)
# print(p1)
# s = str(p1)
# print(s, type(s))

# 9.2 信息格式化操作
# class Person(object):
#     def __init__(self, name, age):
#         self.age = age
#         self.name = name
#
#     # 打印对象的内容 - 描述对象
#     def __str__(self):
#         return '这个人的姓名是：%s, 这是人的年龄是：%s'%(self.name, self.age)
#
#     # 取实例对象的本质信息：面向开发者人员
#     def __repr__(self):
#         return '获取实例对象的本质信息'
#
# p = Person('zb', 23)
# print(repr(p))
# p


# -------------------------------9.3 调用操作__call__ 使一个对象具有函数 被调用的能力 可以通过p()调用----------------------

# class Person(object):
#
#     def __call__(self, *args, **kwargs):
#         print('xxxxx', args, kwargs)
#     pass
# p = Person()
# p()

# 需求： 创建多个画笔  画的的类型（钢笔、铅笔） 画笔的颜色（红色、白、灰色、蓝）

# def createPan(p_color, p_type):
#     print('这是一个%s，它的颜色是%s'%(p_type, p_color))
#
# # 偏函数解决
# import functools
# gangbiFun = functools.partial(createPan, p_type = '钢笔')
# gangbiFun('红色')
# gangbiFun('白色')
# gangbiFun('绿色')

# class PanFactory(object):
#     def __init__(self, p_type):
#         self.p_type = p_type
#
#     def __call__(self, p_color):
#         print('这是一个%s，它的颜色是%s' % (self.p_type, p_color))
#
#
# p = PanFactory('钢笔')
# p('红色')
# p('白色')
# p('绿色')
#
# qianbi = PanFactory('铅笔')
# qianbi('红色')
# qianbi('蓝色')
# qianbi('路色')

# --------------------------------9.4 索引操作:把对象当做字典来操作----------------------
# class Person(object):
#
#     def __init__(self):
#         self.cache = {}
#
#     def __setitem__(self, key, value):
#         print('__setitem__ ---key:%s --value : %s'%(key, value))
#         self.cache[key] = value
#
#     def __getitem__(self, item):
#         print('__getitem__ ---item:%s '%item)
#         return self.cache[key]
#
#     def __delitem__(self, key):
#         print('__delitem__ ---key:', key)
#         del self.cache[key]
#
# p = Person()
# p['name'] = 'zb'
# print(p.__dict__)
# print(p.cache['name'])

# --------------------------------9.5 切片操作:和索引操作的方法一样----------------------
# class Person(object):
#
#     def __init__(self):
#         self.items = ['a', 'b', 'c', 'd', 'e']
#
#     def __setitem__(self, key, value):
#         print('__setitem__ ---key:%s --value : %s'%(key, value))
#         if isinstance(key, slice):
#             self.items[key] = value
#
#     def __getitem__(self, item):
#         print('__getitem__ ---item:%s ' % item)
#
#
# p = Person()
# p[0 : 4 : 2] = [1, 2]
# print(p.items)

# --------------------------------9.6 比较操作:自定义两个对象的比较规则----------------------
# class A(object):
#     # = > < >= <= !
#     def __init__(self, age, height):
#         self.age = age
#         self.height = height
#
#     # =
#     def __eq__(self, other):
#         return self.age == other.age
#
#     # !=
#     def __ne__(self, other):
#         return self.age != other.age
#
#     # >
#     def __gt__(self, other):
#         pass
#
#     # >=
#     def __ge__(self, other):
#         pass
#
#     # <
#     def __lt__(self, other):
#         print('__lt__')
#         return self.age < other.age
#
#     # <=
#     def __le__(self, other):
#         pass
#
# a1 = A(18, 180)
# a2 = A(19, 170)
# # print(a1 != a2)
# print(a1 < a2)
# print(a1 > a2)
# 注意 ： 1、方法不能叠加     2、 b > a  会自动转换为 a < b

# 方案二 利用装饰器 实现<= 方法叠加functools.total_ordering

# import functools
#
# @functools.total_ordering
# class Person(object):
#
#     def __gt__(self, other):
#         print('__gt__')
#         pass
#
#     def __eq__(self, other):
#         print('__eq__')
#
# p1 = Person()
# p2 = Person()
# print(p1 <= p2)


# --------------------------------9.7 比较操作:确定p对象的上下文的bool----------------------
# class Person(object):
#
#     def __init__(self, age):
#         self.age = age
#
#     def __bool__(self):
#         return self.age > 18
#
#
# p = Person(19)
# if p :
#     print('xxxxxx')
# else:
#     print('vvvvvv')


# --------------------------------9.8 遍历操作常用的内置方法----------------------
class Person(object):

    def __init__(self):
        self.result = 0

    # # 方法一实现__getitem__ 方法, 可以是对象遍历
    # def __getitem__(self, item):
    #     self.result += 1
    #     if self.result >= 5:
    #         raise StopIteration('停止运行')
    #     else:
    #         return self.result

    # 方法二 实现__iter__ 、__next__方法, 可以是对象遍历  __iter__ 优先级 大于 __getitem__
    # def __iter__(self):
    #     print('__iter__')
    #     self.result = 1   # 注意：恢复迭代器的初始值
    #     return self
    #
    # def __next__(self):
    #     self.result += 1
    #     if self.result >= 5:
    #         raise StopIteration('停止运行')
    #     else:
    #         return self.result

#p = Person()
# for i in p:
#     print(i)
#
# print(p.result)
#
# for i in p:
#     print(i)

# import collections
# print(isinstance(p, collections.Iterator))
# print(isinstance(p, collections.Iterable))

# p = Person()
# pt = iter(p)
# print(pt)
#
# for i in p:
#     print(i)

# --------------------------------9.9 描述器对象：描述一个属性操作的对象 ：set/get/delete 拦截属性的赋值、删除等操作----------------------

# 1.定义描述器方式1  property

# class Person(object):
#
#     def __init__(self):
#         self.__age = 10
#
#     # 方案一
#     # def get_age(self):
#     #     return self.__age
#     #
#     # def set_age(self, value):
#     #     if value <= 0:
#     #         self.__age = 0
#     #     else:
#     #         self.__age = value
#     #
#     # def delete_age(self):
#     #     del self.__age
#     #
#     # # age 就是描述器
#     # age = property(get_age,set_age,delete_age)
#
#     # 方案二
#     # @property
#     # def age(self):
#     #     return self.__age
#     #
#     # @age.setter
#     # def age(self, value):
#     #     if value <= 0:
#     #         self.__age = 0
#     #     else:
#     #         self.__age = value
#     #
#     # @age.deleter
#     # def age(self):
#     #     del self.__age
#
# p = Person()
# p.age = 19
# print(p.age)

# 2.定义描述器方式2  自定义一个类实现方法 - 只有用于新式类（object） 查找机制是 调用系统的__attrubite__方法

# 资料描述器  实现get  set 方法
# 非资料描述器   只实现get 方法

# # 描述器优先级  资料描述器 > 实例属性  > 非资料描述器
# class Age(object):
#     def __set__(self, instance, value):
#         print('set', self, instance, value)
#         instance.v = value
#
#     def __get__(self, instance, owner):
#         print('get', self, instance, owner)
#         return instance.v
#
#     def __delete__(self, instance):
#         print('delete', self, instance)
#         del instance.v
#
#
# class Person(object):
#     age = Age()
#
#     # def __init__(self):
#     #     self.age = 10
#
# p = Person()
# p.age = 10
# print(p.age, p.__dict__)
# del p.age


# --------------------------------------3.类实现装饰器----------------------

# 3.1 普通装饰器

# def checkName(func):
#     def inner():
#         print('人名字的检测')
#         func()
#     return inner
#
#
# @checkName   #装饰器
# def fashuoshuo():
#     print('发说说。。。。。')
#
# #fashuoshuo = checkName(fashuoshuo)  本质是执行inner函数
# fashuoshuo()

# 3.2 类的装饰器

class checkName(object):

      def __init__(self, func):
          self.func = func

      def __call__(self, *args, **kwargs):
          print('类的装饰器的检测')
          self.func()

@checkName
def fashuoshuo():
    print('发说说。。。。。')

fashuoshuo()




